package netty.selector;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

/**
 * @author cyt
 * @create 2020-11-04 17:21
 */
public class TestServer {

    public static void main(String[] args) throws IOException {
        /**
         * 打开一个通道， 并且还有一个selector
         */
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        Selector selector = Selector.open();
        /**
         * 通道绑定一个 网络地址， 并且配置为非阻塞模式
         * 最后为通道注册一个 selector
         */
        serverSocketChannel.socket().bind(new InetSocketAddress(6767));
        serverSocketChannel.configureBlocking(false);
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        while (true) {
            /**
             * selector.select 在阻塞， 等待连接
             */
            if (selector.select(1000) == 0) {
                System.out.println("等待了 1 秒 ， 没有客户端连接");
                continue;
            }
            /**
             * 一个selector可以注册多个 channel, 此时可以返回 当前selector中注册的所有 channel
             * 并且判断其中的channel 是否有  事件发生。
             */
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                SelectionKey next = iterator.next();
                /**
                 * 有新的客户端在连接
                 */
                if (next.isAcceptable()) {
                    /**
                     * 得到这个连接的通道， 并且注册到 selector 中
                     * 设置好自己的buffer
                     */
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    System.out.println("成功连接一个 " + socketChannel.hashCode());
                    socketChannel.configureBlocking(false);
                    socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));
                }
                /**
                 * 发生是读事件， 反向得到通道，和 buffer
                 * 并且读取这个 buffer中的数据
                 */
                if (next.isReadable()) {
                    SocketChannel channel = (SocketChannel) next.channel();
                    ByteBuffer buffer = (ByteBuffer) next.attachment();

                    channel.read(buffer);
                    System.out.println("from 客户端 " + new String(buffer.array()));
                }
                /*
                删除这个key一次的操作完毕了
                 */
                iterator.remove();
            }
        }
    }
}
